package pl.wr.aspect.performance;

import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import pl.wr.aspect.performance.util.InvokeStatistics;
import pl.wr.aspect.performance.util.PerformanceHelper;

/**
 * @author wieslaw.rodak
 * 
 */
@Aspect
public class ExecutionTimeAspect {

	private Map<String, InvokeStatistics> statisticsMap = new HashMap<String, InvokeStatistics>();

	/**
	 * Call all methods in all class in package <code>pl.wr.test.*</code>
	 * 
	 * @param thisJoinPoint
	 * @return joinPoint result
	 * @throws Throwable
	 */
	@Around("execution(* pl.wr.test..*(..))")
	public Object aroundAllCall(final ProceedingJoinPoint thisJoinPoint) throws Throwable {
		long start = System.currentTimeMillis();
		Object result = thisJoinPoint.proceed();
		long end = System.currentTimeMillis();

		String currentMethod = Modifier.toString(thisJoinPoint.getSignature().getModifiers()) + " "
				+ thisJoinPoint.getSignature().toString();
		InvokeStatistics currentStatistics = statisticsMap.get(currentMethod);
		if (currentStatistics == null) {
			currentStatistics = new InvokeStatistics(currentMethod);
			statisticsMap.put(currentMethod, currentStatistics);
		}
		currentStatistics.addTime(end - start);
		return result;
	}

	/**
	 * Print to System.out.
	 */
	public void printStatistics() {
		List<InvokeStatistics> statistics = PerformanceHelper.sortDescendingByTime(statisticsMap.values());

		for (InvokeStatistics statistic : statistics) {
			System.out.println(statistic);
		}
	}

	/**
	 * @return List of statistics.
	 */
	public List<InvokeStatistics> getStatistics() {
		return PerformanceHelper.sortDescendingByTime(statisticsMap.values());
	}
}
